package com.bitdf.txing.chat.config.handler;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bitdf.txing.chat.constant.Constant;
import com.bitdf.txing.chat.entity.ChatMessageEntity;
import com.bitdf.txing.chat.entity.ReadMessageEntity;
import com.bitdf.txing.chat.service.ChatService;
import com.bitdf.txing.chat.to.AddFriendRequestReplyTo;
import com.bitdf.txing.chat.to.GroupRequestAddTo;
import com.bitdf.txing.common.utils.R;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
@ChannelHandler.Sharable
public class WebSocketServerHandler extends SimpleChannelInboundHandler<WebSocketFrame> {

    @Autowired
    private ChatService chatService;

    public static final ThreadLocal<String> threadLocal = new ThreadLocal<>();

    /**
     * 读取完连接的消息后，对消息进行处理
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame msg) throws Exception {
        handlerWebSocketFrame(ctx, msg);
    }

    /**
     * 处理websocketframe
     * @param ctx
     * @param frame
     */
    private void handlerWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) throws IOException {
        if (frame instanceof CloseWebSocketFrame) {
            WebSocketServerHandshaker handshaker =
                    Constant.webSocketServerHandshakerMap.get(ctx.channel().id().asLongText());
            if (handshaker == null) {
                sendErrorMessage(ctx, "不存在的客户端连接！");
            } else {
                handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain());
            }
            return;
        }
        //ping消息
        if (frame instanceof PingWebSocketFrame) {
            ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
            return;
        }
        if (!(frame instanceof TextWebSocketFrame)) {
            sendErrorMessage(ctx, "仅支持文本格式，不支持二进制消息！");
            return;
        }

//        BinaryWebSocketFrame frame1 = (BinaryWebSocketFrame) frame;
//        ByteBuf content = frame1.content();
//        byte[] array = content.array();

        // 客户端传来的消息
        String request = ((TextWebSocketFrame)frame).text();
        JSONObject param = null;
        try {
            param = JSONObject.parseObject(request);
        } catch (Exception e) {
            sendErrorMessage(ctx, "JSON字符串转换出错！");
            e.printStackTrace();
        }
        if (param == null) {
            sendErrorMessage(ctx, "参数为空！");
            return;
        }

        String type = (String) param.get("messageType");
        Long loginId = -1L;
        if (param.get("satoken") != null) {
            // 获取用户id
            loginId = Long.parseLong((String) StpUtil.getLoginIdByToken((String) param.get("satoken")));
            threadLocal.set((String) param.get("satoken"));
        }

        switch (type) {
            case "single_sending":
                ChatMessageEntity chatMessageEntity = JSON.parseObject(request, ChatMessageEntity.class);
                if (!chatMessageEntity.getFromUserId().equals(loginId)) {
                    chatService.typeError(ctx);
                    break;
                }
                chatService.singleSend(chatMessageEntity, ctx);
                break;
            case "group_sending":
                ChatMessageEntity messageEntity = JSON.parseObject(request, ChatMessageEntity.class);
                if (!messageEntity.getFromUserId().equals(loginId)) {
                    chatService.typeError(ctx);
                    break;
                }
                chatService.groupSend(messageEntity, ctx);
                break;
            case "group_request":
                GroupRequestAddTo groupRequestAddTo = JSON.parseObject(request, GroupRequestAddTo.class);
                if (!groupRequestAddTo.getRequestUserId().equals(loginId)) {
                    chatService.typeError(ctx);
                    break;
                }
                chatService.groupRequestSend(groupRequestAddTo,ctx);
                break;
            case "agree_or_reject_group_request":
                GroupRequestAddTo groupRequestAddTo1 = JSON.parseObject(request, GroupRequestAddTo.class);
                if (!groupRequestAddTo1.getRequestUserId().equals(loginId)) {
                    chatService.typeError(ctx);
                    break;
                }
                chatService.agreeOrRejectGroupRequest(groupRequestAddTo1,ctx);
            case "add_friend_request_reply":
                AddFriendRequestReplyTo addFriendRequestReplyTo = JSON.parseObject(request, AddFriendRequestReplyTo.class);
                if (!addFriendRequestReplyTo.getSendUser().getId().equals(loginId)) {
                    chatService.typeError(ctx);
                    break;
                }
                chatService.addFriendRequestReply(addFriendRequestReplyTo);
            case "agree_or_reject_friend_request":
                AddFriendRequestReplyTo addFriendRequestReplyTo1 = JSON.parseObject(request, AddFriendRequestReplyTo.class);
                if (!addFriendRequestReplyTo1.getReceiveUser().getId().equals(loginId)) {
                    chatService.typeError(ctx);
                    break;
                }
                chatService.agreeOrRejectFriendRequest(addFriendRequestReplyTo1);
                break;
            case "REGISTER":
                // 建立连接后由前端发送“注册”类型消息，消息中带上用户的id， 后端保存该用户id，即保存在线的用户
//                if (! ((Long)Long.parseLong((String) param.get("id"))).equals(loginId)) {
//                    chatService.typeError(ctx);
//                    break;
//                }
                chatService.register(param, ctx);
                break;
            case "read_reply_sending":
                ReadMessageEntity entity = JSON.parseObject(request, ReadMessageEntity.class);
                if (!entity.getReadUserId().equals(loginId)) {
                    chatService.typeError(ctx);
                    break;
                }
                chatService.readReplySend(entity, ctx);
                break;
            default:
                chatService.typeError(ctx);
                break;
        }
    }

    /**
     * 客户端断开连接
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
//        // 通知在线好友我已下线
//        User user = (User) SecurityUtils.getSubject().getPrincipal();
//        List<User> friends = userService.findFriends(user.getId());
//        List<Integer> onlineFriendIds = userService.findOnlineFriendIds(friends);
//        for (int i : onlineFriendIds) {
//            chatService.offlineNotify(user.getId(), Constant.onlineUser.get(String.valueOf(i)));
//        }
        // 去除客户端ctx
        chatService.remove(ctx);
    }

    /**
     * 异常处理，关闭channel
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }




    private void sendErrorMessage(ChannelHandlerContext ctx, String errorMsg) {
        String responseJson = R.error(errorMsg).toString();
        ctx.channel().writeAndFlush(new TextWebSocketFrame(responseJson));
    }
}
